package com.smart.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.smart.common.Constants;
import com.smart.common.PageInfo;
import com.smart.common.domain.BaseEntity;
import com.smart.common.enums.FileStatusEnum;
import com.smart.common.enums.OperateTypeEnum;
import com.smart.common.enums.ProjectConstructionStatusEnum;
import com.smart.common.enums.SmsTemplateEnum;
import com.smart.common.enums.SuperviseModuleEnum;
import com.smart.common.service.LogService;
import com.smart.common.utils.AssertUtil;
import com.smart.mapper.ProjectFileTaskMapper;
import com.smart.model.convert.ProjectConvert;
import com.smart.model.convert.ProjectFileTaskConvert;
import com.smart.model.customdo.ProjectADO;
import com.smart.model.domain.ProjectDO;
import com.smart.model.domain.ProjectFileTaskDO;
import com.smart.model.domain.ProjectFileTaskInstanceDO;
import com.smart.model.dtomapper.ProjectFileTaskDtoMapper;
import com.smart.model.request.ProjectFileTaskAddRequest;
import com.smart.model.request.ProjectFileTaskRequest;
import com.smart.model.request.ProjectFileTaskUpdateRequest;
import com.smart.model.vo.ProjectFileTaskVO;
import com.smart.model.vo.ProjectVO;
import com.smart.service.ProjectFileTaskInstanceService;
import com.smart.service.ProjectFileTaskService;
import com.smart.service.ProjectService;
import com.smart.utils.SmsUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zhanghong
 */
@Service
public class ProjectFileTaskServiceImpl extends ServiceImpl<ProjectFileTaskMapper, ProjectFileTaskDO> implements ProjectFileTaskService {
    @Autowired
    private ProjectFileTaskMapper projectFileTaskMapper;
    @Autowired
    private ProjectFileTaskInstanceService projectFileTaskInstanceService;
    @Autowired
    private ProjectService projectService;
    @Autowired
    private LogService logService;

    @Override
    public ProjectFileTaskVO getByKey(long id) {
        ProjectFileTaskDO projectFileTaskDO = getById(id);
        ProjectFileTaskVO projectFileTaskVO = ProjectFileTaskDtoMapper.INSTANCE.do2VO(projectFileTaskDO);
        return projectFileTaskVO;
    }

    @Override
    public PageInfo<ProjectFileTaskVO> pageQuery(ProjectFileTaskRequest request) {
        long count = projectFileTaskMapper.pageCount(request);
        List<ProjectFileTaskDO> list = projectFileTaskMapper.pageQuery(request, request.getPageSize(), request.fetchOffSet());
        List<ProjectFileTaskVO> projectFileTaskVOList = ProjectFileTaskConvert.buildProjectFileTaskVoList(list);
        fillInfo(projectFileTaskVOList);
        return new PageInfo(request.getPageNum(), request.getPageSize(), projectFileTaskVOList, count);
    }

    private void fillInfo(List<ProjectFileTaskVO> projectFileTaskVOList) {
        for (ProjectFileTaskVO taskVO : projectFileTaskVOList) {
            //统计已读未读
            ProjectFileTaskRequest request = new ProjectFileTaskRequest();
            request.setId(taskVO.getId());

            List<ProjectADO> projectADOS = projectFileTaskMapper.listProjectByCondition(request);
            Long unReceiveNum = projectADOS.stream().filter(item-> Objects.equals(item.getFileReceivedStatus(), 0)).count();
            Long receiveNum = projectADOS.stream().filter(item-> Objects.equals(item.getFileReceivedStatus(), 1)).count();
            taskVO.setUnReceiveNum(unReceiveNum);
            taskVO.setReceiveNum(receiveNum);
        }
    }

    @Override
    public List<ProjectFileTaskVO> listQuery(ProjectFileTaskRequest request) {
        List<ProjectFileTaskDO> list = list();
        List<ProjectFileTaskVO> projectFileTaskVOS = ProjectFileTaskConvert.buildProjectFileTaskVoList(list);
        return projectFileTaskVOS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(ProjectFileTaskAddRequest request) {
        ProjectFileTaskDO projectFileTaskDO = ProjectFileTaskDtoMapper.INSTANCE.request2DO(request);
        projectFileTaskDO.setFileStatus(FileStatusEnum.SEND.name());
        boolean save = save(projectFileTaskDO);
        if (save) {
            //根据编号反推出日期和序号，更新到数据库
            Pair<Date, Long> pair = getFileCodeInfo(request.getFileCode());
            projectFileTaskDO.setFileDate(pair.getLeft());
            projectFileTaskDO.setFileNum(pair.getRight());
            saveOrUpdate(projectFileTaskDO);
        }

        //下发当前文件任务对应的的项目状态
        List<String> unFinishProject = Lists.newArrayList(
                ProjectConstructionStatusEnum.UN_START.name(),
                ProjectConstructionStatusEnum.RUNNING.name(),
                ProjectConstructionStatusEnum.STOP.name(),
                ProjectConstructionStatusEnum.WAIT_ACCEPT.name(),
                ProjectConstructionStatusEnum.DIE.name());
        List<ProjectDO> list = projectService.lambdaQuery()
                .in(ProjectDO::getConstructionStatus, unFinishProject)
                .eq(ProjectDO::getValid, 1)
                .eq(BaseEntity::getDeleted, 0)
                .list();
        if (CollectionUtils.isEmpty(list)) {
            return true;
        }

        Map<Long, ProjectDO> projectMap = list.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<ProjectFileTaskInstanceDO> instanceList = list.stream().map(item -> {
            ProjectFileTaskInstanceDO instanceDO = new ProjectFileTaskInstanceDO();
            instanceDO.setTaskId(projectFileTaskDO.getId());
            instanceDO.setProjectId(item.getId());
            return instanceDO;
        }).collect(Collectors.toList());

        for (ProjectFileTaskInstanceDO instanceDO : instanceList) {
            List<ProjectFileTaskInstanceDO> taskInstanceDOS = projectFileTaskInstanceService.lambdaQuery()
                    .eq(ProjectFileTaskInstanceDO::getProjectId, instanceDO.getProjectId())
                    .eq(ProjectFileTaskInstanceDO::getTaskId, instanceDO.getTaskId())
                    .list();
            if (CollectionUtils.isEmpty(taskInstanceDOS)) {
                projectFileTaskInstanceService.save(instanceDO);
                // 短信发送
                ProjectDO projectDO = projectMap.get(instanceDO.getProjectId());
                if (projectDO != null) {
                    LinkedHashMap<String, String> messages = new LinkedHashMap<>();
                    messages.put("name", String.format("《%s》", request.getFileName()));
                    SmsUtil.sendMessage(projectDO.getShigongContactPhone(), SmsTemplateEnum.SMS_463221254, messages);
                }
            }
        }

        //记录操作日志
        String afterContent = JSON.toJSONString(getById(projectFileTaskDO.getId()));
        logService.logSupervisePlatformAddScene(SuperviseModuleEnum.建设单位管理, projectFileTaskDO.getId(), afterContent);
        return true;
    }

    @Override
    public Boolean updateByKey(ProjectFileTaskUpdateRequest request) {
        ProjectFileTaskDO taskDO = getById(request.getId());
        ProjectFileTaskDO projectFileTaskDO = ProjectFileTaskDtoMapper.INSTANCE.request2DO(request);
        saveOrUpdate(projectFileTaskDO);

        //记录操作日志
        String beforeContent = JSON.toJSONString(taskDO);
        String afterContent = JSON.toJSONString(getById(projectFileTaskDO.getId()));
        logService.logSupervisePlatformUpdateScene(SuperviseModuleEnum.文件下发, projectFileTaskDO.getId(), beforeContent, afterContent);
        return true;
    }

    @Override
    public Boolean deleteByKey(long id) {
        projectFileTaskMapper.deleteDOById(id);
        return true;
    }

    @Override
    public String getFileCode() {
        //查询获取下一个文件编号
        ProjectFileTaskDO recentOne = projectFileTaskMapper.getRecentOne();
        if (recentOne == null || !DateUtil.isSameDay(recentOne.getFileDate(), new Date())) {
            String yyMMdd = DateUtil.format(new Date(), "yyMMdd");
            return MessageFormat.format(Constants.FILE_CODE_TEMPLE, yyMMdd, Constants.FILE_CODE_START_NUM);
        }
        String yyMMdd = DateUtil.format(recentOne.getFileDate(), "yyMMdd");
        return MessageFormat.format(Constants.FILE_CODE_TEMPLE, yyMMdd, recentOne.getFileNum() + Constants.FILE_CODE_START_NUM);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean revokeById(long id) {
        ProjectFileTaskDO projectFileTaskDO = projectFileTaskMapper.selectDOById(id);
        AssertUtil.assertNotNull(projectFileTaskDO, "数据不存在");
        projectFileTaskDO.setFileStatus(FileStatusEnum.REVOKE.name());
        saveOrUpdate(projectFileTaskDO);

        //删除所有未读的实例
        projectFileTaskInstanceService.lambdaUpdate()
                .eq(ProjectFileTaskInstanceDO::getTaskId, projectFileTaskDO.getId())
                .eq(ProjectFileTaskInstanceDO::getStatus, 0)
                .remove();

        //记录操作日志
        String beforeContent = JSON.toJSONString(projectFileTaskDO);
        String afterContent = JSON.toJSONString(getById(projectFileTaskDO.getId()));
        logService.logSupervisePlatform(SuperviseModuleEnum.建设单位管理, OperateTypeEnum.修改, id, beforeContent, afterContent, "撤销");
        return true;
    }

    private Map<String, Object> getExtInfoMap(Long fileTaskId) {
        Map<String, Object> extInfo = Maps.newHashMap();
        ProjectFileTaskRequest request = new ProjectFileTaskRequest();
        request.setId(fileTaskId);

        List<ProjectADO> projectADOS = projectFileTaskMapper.listProjectByCondition(request);
        Long unReceiveNum = projectADOS.stream().filter(item-> Objects.equals(item.getFileReceivedStatus(), 0)).count();
        Long receiveNum = projectADOS.stream().filter(item-> Objects.equals(item.getFileReceivedStatus(), 1)).count();
        //查询
        extInfo.put("receiveNum", receiveNum);
        extInfo.put("unReceiveNum", unReceiveNum);
        extInfo.put("shouldReceiveNum", projectADOS.size());
        return extInfo;
    }

    @Override
    public PageInfo<ProjectVO> projectPageQuery(ProjectFileTaskRequest request) {
        ProjectFileTaskDO projectFileTaskDO = projectFileTaskMapper.selectDOById(request.getId());
        AssertUtil.assertNotNull(projectFileTaskDO, "数据不存在");

        Long count = projectFileTaskMapper.countProjectByCondition(request);
        List<ProjectADO> projects = projectFileTaskMapper.pageProjectByCondition(request, request.getPageSize(), request.fetchOffSet());
        List<ProjectVO> projectVOS = ProjectConvert.buildAdoProjectVoList(projects);
        return PageInfo.build(request.getPageNum(), request.getPageSize(), projectVOS, count, getExtInfoMap(projectFileTaskDO.getId()));
    }

    private Pair<Date, Long> getFileCodeInfo(String fileCode) {
        if (StringUtils.isEmpty(fileCode)) {
            return null;
        }
        fileCode = fileCode.replace("WJ", "");

        String dateStr = fileCode.substring(0, 6);
        String numStr = fileCode.substring(6);

        DateTime fileDate = DateUtil.parse(dateStr, "yyMMdd");
        Long fileNum = Long.parseLong(numStr);
        return Pair.of(fileDate, fileNum);
    }
}
